`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    17:01:46 09/27/2011 
// Design Name: 
// Module Name:    LCD_Fibonauchi_TEST 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module CPU_FSM(CLK, reset);//, SF_D, LCD_E, LCD_RS, LCD_RW);

`include "opcode.v"

input CLK;
input reset;
//output [11:8] SF_D;
//output LCD_E;
//output LCD_RS;
//output LCD_RW;

//wire LCD_E, LCD_RS, LCD_RW;
//wire [11:8] SF_D;

reg [3:0] reg1;
reg [3:0] reg2;

//Enables
reg wr_en,imm_en,reg2_en,regin_en,result_en,RAM_WE,RAM_EN;

reg [3:0] write_address;
reg [7:0] op;

wire [4:0] F;
wire [15:0] RAM_DO;

reg [15:0] imm_data, regin_data, RAM_DI;
reg [9:0] RAM_ADDR;
reg [15:0] IR, PC;
reg [1:0] state,nextstate;

//module REG_ALU_LOGIC(CLK, reset, reg1, reg2, wr_en, write_address, op, regin_data, regin_en, result_en, imm_data, imm_en, reg2_en, F);
REG_ALU_LOGIC Reg_ALU(CLK, reset, reg1, reg2, wr_en, write_address, op, regin_data, regin_en, result_en, imm_data, imm_en, reg2_en, F);


//S3Etest S2eTest(CLK, reset, reg2_data, SF_CE0, SF_D, LCD_E, LCD_RS, LCD_RW);
//lcd_ctrl LCD(CLK, reset, imm_data, SF_D, LCD_E, LCD_RS, LCD_RW);


//RAM(DI,DO,ADDR,CLK,RESET,WE,EN);
RAM RAMBLOCK1(RAM_DI,RAM_DO,RAM_ADDR,CLK,reset,RAM_WE,RAM_EN);

always@(posedge CLK) begin
	if(reset)
		state <= 0;
	else
		state <= nextstate;
end

always@(posedge CLK) begin

	case(state)
	
	fetch: begin
	
		nextstate=decode;
		wr_en = 0;
		imm_en = 0;
		reg2_en = 0;
		regin_en = 0;
		result_en = 0;
		RAM_WE = 0;
		RAM_EN = 0;
		
		RAM_ADDR=PC;
		IR = RAM_DO;
	
	end
	
	decode: begin
	
		nextstate=execute;
	
		reg2_en=0;
		imm_en=0;
		wr_en = 0;
		regin_en = 0;
		result_en = 0;
		RAM_WE = 0;
		RAM_EN = 0;
		
		op = {IR[15:12],IR[7:4]};
		
		case(op)
		
		ADDI: begin
		
			imm_data={{8{0}},IR[7:0]};
			imm_en=1;
			reg2_en=0;
			reg1=IR[11:8];
			
		end
		
		ADD: begin
		
			reg1=IR[3:0];
			reg2=IR[11:8];
			reg2_en=1;
			imm_en=0;
			
		end
		
		endcase
	
	end
	
	execute: begin
	
	   nextstate=store;
		wr_en = 0;
		imm_en = 0;
		reg2_en = 0;
		regin_en = 0;
		result_en = 0;
		RAM_WE = 0;
		RAM_EN = 0;
	
	end
	
	store: begin
	
		nextstate=fetch;
		wr_en=0;
		result_en=0;
		imm_en = 0;
		reg2_en = 0;
		regin_en = 0;
		RAM_WE = 0;
		RAM_EN = 0;
		PC=PC+16;
	
		
	
	
	end
	
	
	default: begin
	
		wr_en = 0;
		imm_en = 0;
		reg2_en = 0;
		regin_en = 0;
		result_en = 0;
		RAM_WE = 0;
		RAM_EN = 0;
		nextstate = fetch;
	end
	
	endcase

end

endmodule
